﻿using System;
using System.ComponentModel;
using System.Drawing;
using System.IO;
using System.Text;
using System.Windows.Forms;
using CrossEntropyProject.Cross_Entropy;
using CrossEntropyProject.GUI;

namespace CrossEntropyProject
{
    public partial class MainForm : Form
    {

        #region constractor MainForm()
        public MainForm()
        {
            InitializeComponent();
          //this code stops the flickiring when moving between panels
            int style = NativeWinAPI.GetWindowLong(this.Handle, NativeWinAPI.GWL_EXSTYLE);
            style |= NativeWinAPI.WS_EX_COMPOSITED;
            NativeWinAPI.SetWindowLong(this.Handle, NativeWinAPI.GWL_EXSTYLE, style);

            this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer, true);

            DataSet.mainForm = this; // allow access to mainForm from DataSet class
            ActiveControl = open_File_btn;//move focus to open_file button
        }
        #endregion

     //Panel1
        //groupBox1
        #region  open_File_btn_Click

        private void open_File_btn_Click(object sender, EventArgs e)
        {
            openFileDialog1.FileName = "";

            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                browseTextBox.Text = "";
                browseTextBox.Update();
                
                try
                {
                    string fileExt = Path.GetExtension(openFileDialog1.FileName);
                    if (fileExt != null && !fileExt.Equals(@".txt"))
                    {
                        String message = "This is not a .txt file, Please reload input file.";
                        MessageBox.Show(message, @"Error - wrong file type", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                    else
                    {
                        Constants.Clear();
                        DataSet.Clear();//clears the data set from loaded data
                        PamMatrixInput.Clear();
                        richTextBox1.Clear();
                        SaveMatrixCheckBox.Checked = false;
                        SaveMatrixCheckBox.Enabled = false;
                        runPam_btn.Enabled = false;
                        num_cluster_select.Enabled = false;
                        results_btn.Enabled = false;
                        next_btn.Enabled = false;
                        open_File_btn.Enabled = false;
                        progressBar1.Visible = true;
                        loading_lbl.Visible = true;
                        percantage_lbl.Visible = true;
                        cancel_btn.Enabled = true;
                        cancel_btn.Visible = true;
                        progressBar1.Value = progressBar1.Minimum;
                        inputFileTextBox.Text = openFileDialog1.FileName;
                        Constants.inputFileName = openFileDialog1.FileName;
                        inputFileTextBox.Select(0, inputFileTextBox.Text.Length); //move cursor position to end of text box 
                        this.Text += " - " + Path.GetFileNameWithoutExtension(openFileDialog1.FileName);
                        backgroundWorker1.RunWorkerAsync();//start the background worker                     
                        Activate_Wait_Cursor();//activate wait cursor when loading input file
                        ActiveControl = cancel_btn;//move focus to cancel button
                    }
                }
                catch (IOException ex)
                {
                    MessageBox.Show(@"Unable to open file:" + openFileDialog1.FileName + 
                          ex.Message, @"Error" , MessageBoxButtons.OK, MessageBoxIcon.Error);
                }

            }
        }
        #endregion


        #region backgroundWorker1 - a thread that reads the input file and updates the progress bar

        internal void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            DataSet.ReadInputFile();
        }

        internal void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            progressBar1.Value = e.ProgressPercentage;
            percantage_lbl.Text = e.ProgressPercentage.ToString() + @"%";
        }

        internal void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (DataSet.loadingCancelled)//check if input file loading was cancelled
            {
                cancel_btn.Visible = false;
                percantage_lbl.Visible = false;
                percantage_lbl.Text = "";
                open_File_btn.Enabled = true;
                inputFileTextBox.Text = "";
                DeActivate_Wait_Cursor();
                DataSet.loadingCancelled = false;
                SaveMatrixCheckBox.Enabled = false;
                open_File_btn.Enabled = true;
                progressBar1.Visible = false;
                loading_lbl.Visible = false;
                percantage_lbl.Visible = false;
                ActiveControl = open_File_btn;
                // Refresh();

            }
            else // file loading completed succesfully
            {
                cancel_btn.Visible = false;           
               // results_btn.Enabled = false;
                SaveMatrixCheckBox.Enabled = true;
                num_cluster_select.Enabled = true;
                DeActivate_Wait_Cursor();
                open_File_btn.Enabled = true;
                MessageBox.Show(@"File opened successfully!", "File opened", MessageBoxButtons.OK, MessageBoxIcon.Information);
                runPam_btn.Enabled = true;
                ActiveControl = runPam_btn;
                // Refresh();
            }

        }

        #endregion


        #region Cancel_btn_Click
        private void cancel_btn_Click(object sender, EventArgs e)
        {
            backgroundWorker1.CancelAsync(); //tell the backgroundWorker to abort
            this.Text = "Cross-Entropy approach for cellular company customer classification";
        }
        #endregion

        //groupBox2
        #region browse_btn_Click

        private void browse_btn_Click(object sender, EventArgs e)
        {
            folderBrowserDialog1.SelectedPath = "";

            if (folderBrowserDialog1.ShowDialog() == DialogResult.OK)
            {
                browseTextBox.Text = folderBrowserDialog1.SelectedPath;
                browseTextBox.Select(0, browseTextBox.Text.Length); //move cursor position to end of text box
                Constants.outputFolderPath = folderBrowserDialog1.SelectedPath;
                browseTextBox.Refresh();
                String matrixFilePath = browseTextBox.Text + @"\" + Constants.name_for_distance_matrix_output_file;
             
                try
                {
                 // print distance matrix to output folder
                    StreamWriter sw = new StreamWriter(matrixFilePath);
                    string str = "";

                    for (int i = 1; i < Constants.numOfhoursInDay; i++)
                    {
                        for (int j = 1; j < Constants.numOfhoursInDay; j++)
                        {
                            str = str + " " + (PamMatrixInput.distanceMatrix[i, j]).ToString();
                        }
                        sw.WriteLine(str);
                        str = "";
                    }
                    sw.Close();

                    MessageBox.Show("'" + Constants.name_for_distance_matrix_output_file + "' has been created at : " + 
                        Constants.outputFolderPath, "", MessageBoxButtons.OK, MessageBoxIcon.Information);

                    ActiveControl = open_File_btn;//move focus to open_file button
                }
                catch (IOException ex)
                {
                    MessageBox.Show(@"Unable to create output file: " + matrixFilePath + ", message: " + ex.Message, "Error",
                       MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }
        #endregion


        #region SaveMatrixCheckBox
        private void SaveMatrixCheckBox_CheckedChanged(object sender, EventArgs e)
        {
            if (SaveMatrixCheckBox.Checked)
            {
                browse_btn.Enabled = true;
                browseTextBox.Text = "";
                ActiveControl = browse_btn;
            }
            else
            {
                browse_btn.Enabled = false;
            }

        }
        #endregion


        #region Main_window_closing
        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            const string message = "Do you sure  you would like to exit?";
            const string caption = "Exit?";

            var result = MessageBox.Show(message, caption, MessageBoxButtons.YesNo, MessageBoxIcon.Question);

            // If the no button was pressed ... 
            if (result == DialogResult.No)
            {
                // cancel the closure of the form.
                e.Cancel = true;
            }
        }
        #endregion

        //groupBox3
        #region see_results_btn_Click
        private void see_results_btn_Click(object sender, EventArgs e)
        {
            if (!backgroundWorker2.IsBusy && !pieChartShowingFlag)
            {
                backgroundWorker2.RunWorkerAsync();//start the thread that builds the pie chart
            }
            else
            {
                MessageBox.Show("Results window is opened ", "Message", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
           
        }
        #endregion


        #region runPam_btn_Click
        private void runPam_btn_Click(object sender, EventArgs e)
        {
            try
            {
                Activate_Wait_Cursor();
                Constants.numOfMedoids = Convert.ToInt32(num_cluster_select.Value);
                runPam_btn.Enabled = false;
                circularProgress2.Visible = true;
                circularProgress2.IsRunning = true;
                richTextBox1.Clear();
                richTextBox1.AppendText("PAM algorithm started...");
                richTextBox1.Update();
                backgroundWorker5.RunWorkerAsync();
                ActiveControl = results_btn;
            }
            catch (Exception ex)
            {
                MessageBox.Show("Problem at PAM algorithm ! " + ex.Message, "", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
        #endregion


        #region backgroundWorker5 - A thread that runs the PAM algorithm
        internal void backgroundWorker5_DoWork(object sender, DoWorkEventArgs e)
        {
            PAM.StartPam();
        }


        internal void backgroundWorker5_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            richTextBox1.AppendText(e.UserState as String);
            richTextBox1.Update();
            richTextBox1.ScrollToCaret();
        }

        internal void backgroundWorker5_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            runPam_btn.Enabled = true;
            circularProgress2.Visible = false;
            circularProgress2.IsRunning = false;
            MessageBox.Show("PAM is done", "Done", MessageBoxButtons.OK, MessageBoxIcon.Information);
            results_btn.Enabled = true;
            hourClusteringToolStripMenuItem.Visible = true;
            seeClusteringResultToolStripMenuItem.Visible = true;
            optionsToolStripMenuItem.Visible = true;
            next_btn.Enabled = true;
            DeActivate_Wait_Cursor();
            ActiveControl = results_btn;
        }
        #endregion


        #region next_btn_Click
        private void next_btn_Click(object sender, EventArgs e)
        {
            numericUpDownNumClustersKmeans.Enabled = true;
            numericUpDownNumClustersKmeans.Value = Constants.defaultNumberOfClustersForKmeans;
            numericUpDownNumSamplesCrossEntropy.Enabled = true;
            numericUpDownNumSamplesCrossEntropy.Value = Constants.defaultNumberOfSamplesForCE;
            numericUpDownSampleSize.Enabled = true;
            numericUpDownSampleSize.Value = Constants.defaultSampleSize;
            numericUpDownNElite.Enabled = true;
            numericUpDownNElite.Value = (decimal)Constants.defaultProportionNEliteSize * 100;
            numericUpDownEpsilonSize.Enabled = true;
            numericUpDownEpsilonSize.Value = (decimal)Constants.defaultEpsilonSize;
            CancelCrossEntropy_btn.Visible = false;
            crossEntropyResults_btn.Visible = false;
            radioButton1.Visible = false;
            radioButton1.Checked = false;
            radioButton2.Visible = false;
            radioButton2.Checked = true;
            radioButton3.Checked = true;

            checkBox1.Checked = true;
            checkBox1.Enabled = true;
            CrossEntropy.saveIterationValuesToFileFlag = checkBox1.Checked;

            crossEntropyRichTextBox.Clear();
            ActiveControl = runCrossEntropy_btn;
            Constants.crossEntropyCancelFlag = false;
            hour_clustering_panel.Visible = false;
            label3.Visible = false;
            cross_entropy_panel.Visible = true;
        }
        #endregion

        
        #region num_cluster_select_ValueChanged
        private void num_cluster_select_ValueChanged(object sender, EventArgs e)
        {
           PAM.k = Convert.ToInt32(num_cluster_select.Value);
        }
        #endregion


        #region exitToolStripMenuItem_Click
        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }
        #endregion


        #region aboutToolStripMenuItem_Click
        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            AboutForm ab = new AboutForm();
            ab.ShowDialog();
        }
        #endregion


        #region newToolStripMenuItem_Click
        private void newToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //restore every GUI component to default , clear the data structures and abort any ongoing processes 

            cancel_btn.Enabled = true;
            cancel_btn.PerformClick();
            cancel_btn.Enabled = false;
            cancel_btn.Visible = false;

            SaveMatrixCheckBox.Checked = false;
            richTextBox1.Clear();
            groupBox1.Enabled = true;

            inputFileTextBox.Text = "";
            browseTextBox.Text = "";
            percantage_lbl.Text = "";
            percantage_lbl.Visible = false;
            progressBar1.Visible = false;
            loading_lbl.Visible = false;
            progressBar1.Value = progressBar1.Minimum;


            SaveMatrixCheckBox.Enabled = false;
            runPam_btn.Enabled = false;
            num_cluster_select.Enabled = false;

            next_btn.Enabled = false;
            results_btn.Enabled = false;
            optionsToolStripMenuItem.Visible = false;
            hourClusteringToolStripMenuItem.Visible = false;
            seeClusteringResultToolStripMenuItem.Visible = false;
            saveResults_btn.Visible = false;
            num_cluster_select.Value = 3;
            //if the results windows are open then close them
            if (pch != null)
            {
               pch.Close();
            }
            if (cf != null)
            {
               cf.Close();
            }
            this.Text = "Cross-Entropy approach for cellular company customer classification";

            Constants.defaultNumberOfClustersForKmeans = 3;
            Constants.defaultNumberOfSamplesForCE = 100;
            Constants.defaultSampleSize = 50000;
            Constants.defaultProportionNEliteSize = 0.1;
            Constants.defaultEpsilonSize = 0.0000001;


            hour_clustering_panel.Visible = true;
            cross_entropy_panel.Visible = false;
            customerClusteringToolStripMenuItem.Visible = false;
            ActiveControl = open_File_btn;
        }
        #endregion


        #region howToUseToolStripMenuItem_Click
        private void howToUseToolStripMenuItem_Click(object sender, EventArgs e)
        {
            HowToUseForm htf = new HowToUseForm();
            htf.ShowDialog();
        }
        #endregion


        #region hourClusteringToolStripMenuItem_Click
        private void hourClusteringToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (!backgroundWorker2.IsBusy && !pieChartShowingFlag)
            {
                backgroundWorker2.RunWorkerAsync();//start the thread that builds the pie chart
            }
            else
            {
                MessageBox.Show("Results window is opened ","Message", MessageBoxButtons.OK, MessageBoxIcon.Information); 
            }
           
        }
        #endregion


        #region customerClusteringToolStripMenuItem_Click
        internal void customerClusteringToolStripMenuItem_Click(object sender, EventArgs e)
        {
            backgroundWorker4.RunWorkerAsync();
        } 
        #endregion


        #region backgroundWorker2 - a thread that builds and shows the pie chart
        private void backgroundWorker2_DoWork(object sender, DoWorkEventArgs e)
        {
            pch = new PieChartForm();
            if (cf!=null)
            {
                pch.Location = new Point((cf.ClientSize.Width + 40), 20);
            }
            else
            {
                Screen sr = Screen.PrimaryScreen;
                int height = sr.WorkingArea.Height;
                int width = sr.WorkingArea.Width;

                pch.Location = new Point((width / 2) - (pch.ClientSize.Width / 2), (height / 2) - (pch.ClientSize.Height / 2));
                   
            }
        }
        private void backgroundWorker2_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            pieChartShowingFlag = true;
            pch.Show();
        }
        #endregion


        //============ Cross-Entropy Panel =================================================================================================

        #region backgroundWorker3 - a thread that runs the cross-entropy method and update the logbox in the cross-entropy panel
        //this back ground worker is for running the cross-entropy method
        internal void backgroundWorker3_DoWork(object sender, DoWorkEventArgs e)
        {
            CrossEntropy.StartCrossEntropyMethod();
        }

        internal void backgroundWorker3_ProgressChanged(object sender,ProgressChangedEventArgs e)
        {
            crossEntropyRichTextBox.AppendText(e.UserState as String);
            crossEntropyRichTextBox.Update();
            crossEntropyRichTextBox.ScrollToCaret();
            
        }

        internal void backgroundWorker3_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (Constants.crossEntropyCancelFlag)//the cross entropy method was canceled
            {
                Constants.crossEntropyCancelFlag = false;
                crossEntropyRichTextBox.AppendText(Environment.NewLine + "Canceled!");
                numericUpDownNumClustersKmeans.Enabled = true;
                numericUpDownNumSamplesCrossEntropy.Enabled = true;
                numericUpDownSampleSize.Enabled = true;
                numericUpDownNElite.Enabled = true;
                numericUpDownEpsilonSize.Enabled = true;
                CancelCrossEntropy_btn.Visible = false;
                runCrossEntropy_btn.Enabled = true;
                circularProgress1.Visible = false;
                circularProgress1.IsRunning = false;
                DeActivate_Wait_Cursor();
                radioButton3.Enabled = true;
                radioButton4.Enabled = true;
                checkBox1.Enabled = true;
                Update();
                ActiveControl = runCrossEntropy_btn;
            }
            else //the cross entropy method completed!
            {
                circularProgress1.Visible = false;
                circularProgress1.IsRunning = false;
                MessageBox.Show("Cross Entropy is done", "Done", MessageBoxButtons.OK, MessageBoxIcon.Information);
                label3.Visible = true;
                crossEntropyResults_btn.Visible = true;
                radioButton1.Visible = true;
                radioButton2.Visible = true;
                CancelCrossEntropy_btn.Visible = false;
                DeActivate_Wait_Cursor();
                numericUpDownNumClustersKmeans.Enabled = true;
                numericUpDownNumSamplesCrossEntropy.Enabled = true;
                numericUpDownSampleSize.Enabled = true;
                numericUpDownNElite.Enabled = true;
                numericUpDownEpsilonSize.Enabled = true;
                runCrossEntropy_btn.Enabled = true;
                customerClusteringToolStripMenuItem.Visible = true;
                LoadRegularDataFlag = radioButton2.Checked;
                saveResults_btn.Visible = true;
                radioButton3.Enabled = true;
                radioButton4.Enabled = true;
                checkBox1.Enabled = true;
                Update();
                ActiveControl = crossEntropyResults_btn;
            }
        } 
        #endregion


        #region runCrossEntropy_btn_Click
        private void runCrossEntropy_btn_Click(object sender, EventArgs e)
        {
            numericUpDownNumClustersKmeans.Enabled = false;
            numericUpDownNumSamplesCrossEntropy.Enabled = false;
            numericUpDownSampleSize.Enabled = false;
            numericUpDownNElite.Enabled = false;
            numericUpDownEpsilonSize.Enabled = false;
            CancelCrossEntropy_btn.Visible = true;
            crossEntropyResults_btn.Visible = false;
            radioButton1.Visible = false;
            radioButton2.Visible = false;
            radioButton3.Enabled = false;
            radioButton4.Enabled = false;
            checkBox1.Enabled = false;
            saveResults_btn.Visible = false;
            runCrossEntropy_btn.Enabled = false;
            label3.Visible = false;
            Update();
            //if the results windows are open then close them
            if (pch != null)
            {
                pch.Close();
            }
            if (cf != null)
            {
                cf.Close();
            }
            Activate_Wait_Cursor();
            crossEntropyRichTextBox.Clear();
            String str = "Cross-Entropy Method Started...";

            circularProgress1.IsRunning = true;
            circularProgress1.Visible = true;
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < str.Length; i++)
            {
                sb.Append("*");
            }

            crossEntropyRichTextBox.AppendText(str);
            crossEntropyRichTextBox.AppendText(Environment.NewLine + sb.ToString());
            backgroundWorker3.RunWorkerAsync();//start the background worker 
    
        } 
        #endregion


        #region CancelCrossEntropy_btn_Click
        private void CancelCrossEntropy_btn_Click(object sender, EventArgs e)
        {
            crossEntropyRichTextBox.AppendText(Environment.NewLine + "Canceling...");
            backgroundWorker3.CancelAsync(); //tell the backgroundWorker to abort
        } 
        #endregion


        #region numericUpDownNumClustersKmeans_ValueChanged
        private void numericUpDownNumClustersKmeans_ValueChanged(object sender, EventArgs e)
        {
            try
            {
                int value = Convert.ToInt32(numericUpDownNumClustersKmeans.Text);
                if (value > numericUpDownNumClustersKmeans.Maximum || value < numericUpDownNumClustersKmeans.Minimum)
                {
                    string msg = "this value must be between " + numericUpDownNumClustersKmeans.Minimum.ToString() +
                                                        " and " + numericUpDownNumClustersKmeans.Maximum.ToString();
                    MessageBox.Show(msg, "Wrong value", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                else
                {
                    //CrossEntropy.numberOfClusters = Convert.ToInt32(numericUpDownNumClustersKmeans.Value);
                   Constants.defaultNumberOfClustersForKmeans = Convert.ToInt32(numericUpDownNumClustersKmeans.Value);
                }
            }
            catch (Exception)
            {

                string msg = "this value must be integer between " + numericUpDownNumClustersKmeans.Minimum.ToString() +
                                    " and " + numericUpDownNumClustersKmeans.Maximum.ToString();
                MessageBox.Show(msg, "Wrong value", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

        } 
        #endregion


        #region numericUpDownNumSamplesCrossEntropy_ValueChanged
        private void numericUpDownNumSamplesCrossEntropy_ValueChanged(object sender, EventArgs e)
        {
            try
            {
                int value = Convert.ToInt32(numericUpDownNumSamplesCrossEntropy.Text);
                if (value > numericUpDownNumSamplesCrossEntropy.Maximum || value < numericUpDownNumSamplesCrossEntropy.Minimum)
                {
                    string msg = "this value must be between " + numericUpDownNumSamplesCrossEntropy.Minimum.ToString() +
                                                        " and " + numericUpDownNumSamplesCrossEntropy.Maximum.ToString();
                    MessageBox.Show(msg, "Wrong value", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                else
                {
                    //CrossEntropy.numberOfSamples = Convert.ToInt32(numericUpDownNumSamplesCrossEntropy.Value);
                    Constants.defaultNumberOfSamplesForCE = Convert.ToInt32(numericUpDownNumSamplesCrossEntropy.Value);
                }
            }
            catch (Exception)
            {

                string msg = "this value must be integer between " + numericUpDownNumSamplesCrossEntropy.Minimum.ToString() +
                                    " and " + numericUpDownNumSamplesCrossEntropy.Maximum.ToString();
                MessageBox.Show(msg, "Wrong value", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
     
        } 
        #endregion


        #region numericUpDownSampleSize_ValueChanged
        private void numericUpDownSampleSize_ValueChanged(object sender, EventArgs e)
        {
            try
            {
                int value = Convert.ToInt32(numericUpDownSampleSize.Text);
                if (value > numericUpDownSampleSize.Maximum || value < numericUpDownSampleSize.Minimum)
                {
                    string msg = "this value must be between " + numericUpDownSampleSize.Minimum.ToString() +
                                                        " and " + numericUpDownSampleSize.Maximum.ToString();
                    MessageBox.Show(msg, "Wrong value", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                else
                {
                    //CrossEntropy.sampleSize = Convert.ToInt32(numericUpDownSampleSize.Value);
                    Constants.defaultSampleSize = Convert.ToInt32(numericUpDownSampleSize.Value);
                }
            }
            catch (Exception)
            {

                string msg = "this value must be integer between " + numericUpDownSampleSize.Minimum.ToString() +
                                     " and " + numericUpDownSampleSize.Maximum.ToString();
                MessageBox.Show(msg, "Wrong value", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

        } 
        #endregion


        #region numericUpDownNElite_ValueChanged
        private void numericUpDownNElite_ValueChanged(object sender, EventArgs e)
        {
            try
            {
                double value = Convert.ToDouble(numericUpDownNElite.Text);
                if (value > Convert.ToDouble(numericUpDownNElite.Maximum) || value < Convert.ToDouble(numericUpDownNElite.Minimum))
                {
                    string msg = "this value must be between " + numericUpDownNElite.Minimum.ToString() +
                                                        " and " + numericUpDownNElite.Maximum.ToString();
                    MessageBox.Show(msg, "Wrong value", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                else
                {
                    //CrossEntropy.proportionNEliteSamples = Convert.ToDouble(numericUpDownNElite.Value) / 100;
                    Constants.defaultProportionNEliteSize = (Convert.ToDouble(numericUpDownNElite.Value) / Convert.ToDouble(100));
                }
            }
            catch (Exception)
            {

                string msg = "this value must be between " + numericUpDownNElite.Minimum.ToString() +
                                    " and " + numericUpDownNElite.Maximum.ToString();
                MessageBox.Show(msg, "Wrong value", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
    
        } 
        #endregion


        #region numericUpDownEpsilonSize_ValueChanged
        private void numericUpDownEpsilonSize_ValueChanged(object sender, EventArgs e)
        {
            try
            {
                double value = Convert.ToDouble(numericUpDownEpsilonSize.Text);
                if (value > Convert.ToDouble(numericUpDownEpsilonSize.Maximum) || value < Convert.ToDouble(numericUpDownEpsilonSize.Minimum))
                {
                    string msg = "this value must be between " + numericUpDownEpsilonSize.Minimum.ToString() +
                                                        " and " + numericUpDownEpsilonSize.Maximum.ToString();
                    MessageBox.Show(msg, "Wrong value", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                else
                {
                    //CrossEntropy.epsilon = Convert.ToDouble(numericUpDownEpsilonSize.Value);
                    Constants.defaultEpsilonSize = Convert.ToDouble(numericUpDownEpsilonSize.Value);
                }
            }
            catch (Exception)
            {
                string msg = "this value must be between " + numericUpDownEpsilonSize.Minimum.ToString() +
                                     " and " + numericUpDownEpsilonSize.Maximum.ToString();
                MessageBox.Show(msg, "Wrong value", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

        } 
        #endregion


        #region crossEntropyResults_Click
        internal void crossEntropyResults_Click(object sender, EventArgs e)
        {
            if (!backgroundWorker4.IsBusy && !chartShowingFlag)
            {
                backgroundWorker4.RunWorkerAsync();//start the thread that builds the pie chart
            }
            else
            {
                MessageBox.Show("Results window is opened ", "Message", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        } 
        #endregion


        #region backgroundWorker4_DoWork - a thread that shows the profiles
        internal void backgroundWorker4_DoWork(object sender, DoWorkEventArgs e)
        {
            cf = new chartsForm(this, LoadRegularDataFlag);
            chartShowingFlag = true;
            cf.Location = new Point(12, 12);
        }

        internal void backgroundWorker4_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            cf.Show();
            if (!pieChartShowingFlag && LoadRegularDataFlag)
            {
                hourClusteringToolStripMenuItem.PerformClick();
            }

        }
        #endregion


        #region radio buttons
        internal void radioButton2_CheckedChanged(object sender, EventArgs e)
        {
            LoadRegularDataFlag = radioButton2.Checked;
            radioButton1.Checked = !radioButton2.Checked;
            Update();
        }

        internal void radioButton1_CheckedChanged(object sender, EventArgs e)
        {
            LoadRegularDataFlag = !radioButton1.Checked;
            radioButton2.Checked = !radioButton1.Checked;
            Update();
        }

        internal void radioButton3_CheckedChanged(object sender, EventArgs e)
        {
            CrossEntropy.useUnionNeliteSamplesFlag = radioButton3.Checked;
           // radioButton4.Checked = !radioButton3.Checked;
            //Update();
        }

        internal void radioButton4_CheckedChanged(object sender, EventArgs e)
        {
           // CrossEntropy.useUnionNeliteSamplesFlag = radioButton4.Checked;
            //radioButton3.Checked = !radioButton4.Checked;
           // Update();
        }
        #endregion


        #region  saveResults_btn_Click
        internal void saveResults_btn_Click(object sender, EventArgs e)
        {
            if (!backgroundWorker6.IsBusy)
            {
                circularProgress3.Visible = true;
                circularProgress3.IsRunning = true;
                backgroundWorker6.RunWorkerAsync();
            }
            else
            {
                MessageBox.Show("Saving process ongoing please wait for it to finish ", "Message", MessageBoxButtons.OK,
                    MessageBoxIcon.Information);
            }  
        } 
        #endregion


        #region backgroundWorker6 - runs the saving results process
        private void backgroundWorker6_DoWork(object sender, DoWorkEventArgs e)
        {
            DataSet.SaveClusteringResults();
        }

        private void backgroundWorker6_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            circularProgress3.Visible = false;
            circularProgress3.IsRunning = false;
            MessageBox.Show("Results has been saved to: " + Constants.targetPath, "", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }
        #endregion


        #region checkBox1_CheckedChanged
        private void checkBox1_CheckedChanged(object sender, EventArgs e)
        {
            CrossEntropy.saveIterationValuesToFileFlag = checkBox1.Checked;
        } 
        #endregion

//++++++++++++++++++++++++++++++++++++++++++++++++++

        #region CloseTogether()
        internal void CloseTogether()
        {
            if (pch != null)
            {
                cf.Dispose();
                pch.Close();
                pch.Dispose();
                pch = null;
                cf = null;
                pieChartShowingFlag = false;
            }
        } 
        #endregion


        #region Wait_Cursor activator and deactivator
        internal void Activate_Wait_Cursor()
        {
           Cursor = Cursors.AppStarting;
        }
        internal void DeActivate_Wait_Cursor()
        {
            this.Cursor = System.Windows.Forms.Cursors.Default;
        }
        #endregion


        #region MainForm_FormClosed()
        private void MainForm_FormClosed(object sender, FormClosedEventArgs e)
        {
            Dispose();
            Application.ExitThread();
        } 
        #endregion 

    }//partial class

}//namespace
